/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.meuevento.business.general;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;

/**
 *
 * @author Fernando Arena Varella <favarella@inf.ufrgs.br>
 */
@Stateless
@Local
public class CrudService<T> {

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method" or "Web Service > Add Operation")
    @PersistenceContext
    EntityManager em;

    public T create(T t) {
        this.em.persist(t);
        this.em.flush();
        this.em.refresh(t);
        return t;
    }

    @SuppressWarnings("unchecked")
    public T find(Class type, Object id) {
        return (T) this.em.find(type, id);
    }

    public void delete(Class type, Object id) {
        Object ref = this.em.getReference(type, id);
        this.em.remove(ref);
    }

    public T update(T t) {
        t = this.em.merge(t);
//        this.em.flush();
//        this.em.refresh(t);
        return t;
    }

    public List<T> findAll(Class clazz){
        String[] names = clazz.getName().split("\\.");
        //A função está se perdendo qdo tem pacotes no nome, essa gamb
        //de cima é para pegar apenas o último nome
        return em.createQuery("select o from " + names[names.length-1] +
                " as o").getResultList();

//        CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(clazz);
//        CriteriaQuery<T> c = em.getQueryBuilder().createQuery(clazz);
//        TypedQuery<T> q = em.createQuery(c);
//        return q.getResultList();
    }

    public List findWithNamedQuery(String namedQueryName) {
        return this.em.createNamedQuery(namedQueryName).getResultList();
    }

    public List findWithNamedQuery(String namedQueryName, Map parameters) {
        return findWithNamedQuery(namedQueryName, parameters, 0);
    }

    public List findWithNamedQuery(String queryName, int resultLimit) {
        return this.em.createNamedQuery(queryName).
                setMaxResults(resultLimit).
                getResultList();
    }

    public List findWithNamedQuery(String queryName,int firstResult, int resultLimit) {
        return this.em.createNamedQuery(queryName).
                setFirstResult(firstResult).
                setMaxResults(resultLimit).
                getResultList();
    }


    public List findByNativeQuery(String sql, Class type) {
        return this.em.createNativeQuery(sql, type).getResultList();
    }

    public List findWithNamedQuery(String namedQueryName, Map parameters, int resultLimit) {
        Set<Entry> rawParameters = parameters.entrySet();
        Query query = this.em.createNamedQuery(namedQueryName);
        if (resultLimit > 0) {
            query.setMaxResults(resultLimit);
        }
        for (Entry entry : rawParameters) {
            query.setParameter(entry.getKey().toString(), entry.getValue());
        }
        return query.getResultList();
    }

    public List findWithNamedQuery(String namedQueryName, Map parameters,
            int firstResult, int resultLimit) {
        Set<Entry> rawParameters = parameters.entrySet();
        Query query = this.em.createNamedQuery(namedQueryName);
        if (resultLimit > 0) {
            query.setMaxResults(resultLimit);
        }
        if (firstResult > 0)
            query.setFirstResult(firstResult);

        for (Entry entry : rawParameters) {
            query.setParameter(entry.getKey().toString(), entry.getValue());
        }
        return query.getResultList();
    }



}
